package pers.mihao.quickstream.common.task.repository.impl;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.support.TransactionTemplate;
import pers.mihao.quickstream.common.exception.BaseException;
import pers.mihao.quickstream.common.task.constans.TaskStatus;
import pers.mihao.quickstream.common.task.dto.AutomaticTaskDTO;
import pers.mihao.quickstream.common.task.dto.UniqueBizInfo;
import pers.mihao.quickstream.common.task.dto.convertor.TaskConvert;
import pers.mihao.quickstream.common.task.repository.AutomaticTaskRepository;
import pers.mihao.quickstream.common.task.repository.domain.AutomaticTaskDO;
import pers.mihao.quickstream.common.task.repository.mapper.AutomaticTaskMapper;
import pers.mihao.quickstream.common.util.AssertUtil;
import pers.mihao.quickstream.common.util.Query;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author mihao
 * @since 2024/11/15
 */
@Repository
public class AutomaticTaskRepositoryImpl implements AutomaticTaskRepository {

    @Resource
    AutomaticTaskMapper automaticTaskMapper;

    @Resource
    TransactionTemplate transactionTemplate;

    @Override
    public void saveAutomaticTask(AutomaticTaskDTO automaticTaskDTO) {
        AssertUtil.notNull(automaticTaskDTO);
        AutomaticTaskDO automaticTaskDO = TaskConvert.INSTANCE.map2TaskDO(automaticTaskDTO);
        if (automaticTaskDTO.getId() != null) {
            transactionTemplate.execute(c -> {
                AssertUtil.isTrue(automaticTaskMapper.updateByIdWithVersion(automaticTaskDO) == 1);
                return c;
            });
        } else {
            transactionTemplate.execute(c -> {
                AssertUtil.isTrue(automaticTaskMapper.insert(automaticTaskDO) == 1);
                return c;
            });
        }

    }

    @Override
    public AutomaticTaskDTO queryByBizId(UniqueBizInfo uniqueBizInfo) {
        AutomaticTaskDO automaticTaskDO = automaticTaskMapper.selectOne(new Query<AutomaticTaskDO>()
                .eq("bizId", uniqueBizInfo.getBizId())
                .eq("bizType", uniqueBizInfo.getBizType()));
        return TaskConvert.INSTANCE.map2TaskDTO(automaticTaskDO);
    }

    @Override
    public List<AutomaticTaskDTO> queryWaitToScheduler(Long timeRange) {
        List<AutomaticTaskDO> nextInvokeTime = automaticTaskMapper.selectList(new Query<AutomaticTaskDO>()
                .le("nextInvokeTime", new Date(System.currentTimeMillis() + timeRange))
                .eq("status", TaskStatus.TOBE_SCHEDULER.name()));
        return Optional.ofNullable(nextInvokeTime).orElse(new ArrayList<>())
                .stream().map(TaskConvert.INSTANCE::map2TaskDTO).collect(Collectors.toList());
    }

    @Override
    public void batchUpdateStatus(List<AutomaticTaskDTO> taskS) {
        transactionTemplate.execute(t -> {
            for (AutomaticTaskDTO task : taskS) {
                int i = automaticTaskMapper.updateStatus(task.getId(), task.getStatus().name(), task.getVersion());
                if (i != 1) {
                    t.setRollbackOnly();
                    throw new BaseException("数据库操作异常");
                }
            }
            return t;
        });
    }
}
